package fueltrack.client.ui;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.extjs.gxt.ui.client.data.BaseListLoadConfig;
import com.extjs.gxt.ui.client.data.BaseListLoadResult;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.IconButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.Composite;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.ToolButton;
import com.extjs.gxt.ui.client.widget.form.Field;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.jhickman.web.gwt.gxtuibinder.client.GxtEvent;
import com.jhickman.web.gwt.gxtuibinder.client.GxtUiHandler;

import fueltrack.client.FuelTrackDataServiceAsync;
import fueltrack.client.FuelTrackEntry;

public class FuelTrackUI extends Composite /* implements HasText */{

	private static FuelTrackUIUiBinder uiBinder = GWT.create(FuelTrackUIUiBinder.class);

	interface FuelTrackUIUiBinder extends UiBinder<Component, FuelTrackUI> {
	}

	private FuelTrackDataServiceAsync fuelTrackDataService;

	@UiField
	Grid<ModelData> grid;
	@UiField
	ContentPanel entriesPanel;

	@UiField
	FormPanel newEntryForm;

	@UiField(provided = true)
	ListStore<ModelData> store;

	private BaseListLoader<ListLoadResult<ModelData>> loader;
	
	public FuelTrackUI(final FuelTrackDataServiceAsync fuelTrackDataService) {
		this.fuelTrackDataService = fuelTrackDataService;
		
		loader = new BaseListLoader<ListLoadResult<ModelData>>(new RpcProxy<ListLoadResult<ModelData>>() {
			@Override
			protected void load(Object loadConfig, final AsyncCallback<ListLoadResult<ModelData>> callback) {
				boolean force = ((BaseListLoadConfig) loadConfig).get("force", false);
				
				fuelTrackDataService.getFuelTrackEntries(force, new AsyncCallback<List<FuelTrackEntry>>() {
					@Override
					public void onSuccess(List<FuelTrackEntry> result) {
						List<ModelData> models = new ArrayList<ModelData>();
						
						for (FuelTrackEntry entry : result) {
							BaseModelData model = new BaseModelData();
							
							model.set("date", entry.getDate());
							model.set("odometer", entry.getOdometer());
							model.set("tripMeter", entry.getTripMeter());
							model.set("litres", entry.getLitres());
							model.set("amount", entry.getAmount());
							
							models.add(model);
						}
						callback.onSuccess(new BaseListLoadResult<ModelData>(models));
					}
					
					@Override
					public void onFailure(Throwable caught) {
						callback.onFailure(caught);
					}
				});
			}
		});
		
//		ModelType type = new ModelType();  
//		type.setRoot("records");  
//		type.addField("domain", "domain");  
//		type.addField("name", "name");  
//		type.addField("symbol", "symbol");  
//		type.addField("last", "last");  
//		type.addField("change", "change");  
//		type.addField("date", "date"); 
//		final BaseListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(new MemoryProxy<ListLoadResult<ModelData>>("{'records': [{'domain': 'A', 'name': 'A', 'symbol': 'A', 'last': 3, 'change': 0.1, 'date': '2012-01-12'}]}"), new JsonLoadResultReader<ListLoadResult<ModelData>>(type));
		
		
		store = new ListStore<ModelData>(loader);
		
		initComponent(uiBinder.createAndBindUi(this));
		
		ToolButton refreshButton = new ToolButton("x-tool-refresh");
		refreshButton.addSelectionListener(new SelectionListener<IconButtonEvent>() {
			@Override
			public void componentSelected(IconButtonEvent ce) {
				reloadGrid(true);
			}
		});
		entriesPanel.getHeader().addTool(refreshButton);
		
		reloadGrid(false);
	}
	
	@GxtUiHandler(uiField = "newEntrySubmitButton", eventType = GxtEvent.OnClick)
	void doNewEntrySubmitClick(ButtonEvent e) {
		FuelTrackEntry entry = new FuelTrackEntry();
		
		for (Field<?> field : newEntryForm.getFields()) {
			if ("date".equalsIgnoreCase(field.getName())) {
				entry.setDate(new Date());
			} else if ("odometer".equalsIgnoreCase(field.getName())) {
				entry.setOdometer(((Double) field.getValue()).longValue());
			} else if ("tripMeter".equalsIgnoreCase(field.getName())) {
				entry.setTripMeter(((Double) field.getValue()));
			} else if ("litres".equalsIgnoreCase(field.getName())) {
				entry.setLitres(((Double) field.getValue()));
			} else if ("amount".equalsIgnoreCase(field.getName())) {
				entry.setAmount(((Double) field.getValue()));
			} 
		}
		
		fuelTrackDataService.addFuelTrackEntry(entry, new AsyncCallback<Void>() {
			@Override
			public void onSuccess(Void result) {
				reloadGrid(false);
				newEntryForm.clear();
			}
			@Override
			public void onFailure(Throwable caught) {
				MessageBox.alert("Service Error", "There was an error whilst trying to save the new entry\n" + caught.getLocalizedMessage(), null);
			}
		});
	}
	
	@GxtUiHandler(uiField = "newEntryCancelButton", eventType = GxtEvent.OnClick)
	void doNewEntryCancelClick(ButtonEvent e) {
		newEntryForm.clear();
	}
	
	private void reloadGrid(boolean force) {
		BaseListLoadConfig loadConfig = new BaseListLoadConfig();
		loadConfig.set("force", force);
		
		loader.load(loadConfig);
	}
}
